use async_trait::async_trait;
use clap::Parser;
use hmac::{Hmac, Mac};
use sha2::{Sha256, Sha512};

use crate::commands::commands::Command;
use crate::models::models;
use crate::models::models::command::CommandState;
use crate::utils::command;

#[derive(Debug, Default, Clone, Parser)]
#[clap(disable_help_flag = true)]
struct Args {
    // 使用SHA512算法
    #[arg(short = '5', long = "512", default_value_t = false)]
    s_512: bool,
    // 加密key
    #[arg(short = 'k', long = "key", default_value = "")]
    key: String,
    // 是否转为大写
    #[arg(short = 'u', long = "upper", default_value_t = false)]
    upper: bool,
    // 字符串
    value: String,
}

#[derive(Debug, Default, Clone)]
pub(crate) struct HmacCommand {}

#[async_trait]
impl Command for HmacCommand {
    async fn execute(&self, command: models::command::Command) -> models::command::Command {
        let args = command::parse_command_args::<Args>(command.args.as_str());
        if args.is_err() {
            return self.save_command_output(command, CommandState::Success, args.unwrap_err().to_string());
        }

        let args = args.unwrap();

        if args.key.is_empty() {
            return self.save_command_output(command, CommandState::Success, "必须指定-k或--key参数".to_string());
        }

        if args.s_512 {
            let hasher = Hmac::<Sha512>::new_from_slice(args.key.as_bytes());
            if hasher.is_err() {
                return self.save_command_output(command, CommandState::Success, "创建HMAC-SHA512加密器失败".to_string());
            }

            let mut hasher = hasher.unwrap();
            hasher.update(args.value.as_bytes());

            let mut result = format!("{:x}", hasher.finalize().into_bytes());
            if args.upper {
                result = result.to_uppercase();
            }

            return self.save_command_output(command, CommandState::Success, result);
        }

        let hasher = Hmac::<Sha256>::new_from_slice(args.key.as_bytes());
        if hasher.is_err() {
            return self.save_command_output(command, CommandState::Success, "创建HMAC-SHA256加密器失败".to_string());
        }

        let mut hasher = hasher.unwrap();
        hasher.update(args.value.as_bytes());

        let mut result = format!("{:x}", hasher.finalize().into_bytes());
        if args.upper {
            result = result.to_uppercase();
        }

        self.save_command_output(command, CommandState::Success, result)
    }
}